// const express = require("express") commonJs 规范
import React from "react";
import express from "express";
// import Home from "../pages/Home";
// 服务端会因为 ssr 消耗服务端的性能， react 消耗 CPU 的性能
import { renderToString } from "react-dom/server";
import { Provider } from "react-redux";
import { StaticRouter, Switch, Route } from "react-router-dom";
import { matchRoutes, renderRoutes } from "react-router-config";
import proxy from "express-http-proxy";
import { Header } from "../components/Header";
import { getStore } from "../store";
import { routes } from "../routes";

// 实现服务器重定向, 在 react-router-config 会向 context 中注入一个 replace 的路由

const app = express()

// 配置静态资源目录, static 是一个中间件
app.use(express.static("public"))

// 请求的是 api 时， 进行代理
app.use("/api", proxy("https://gank.io", {
  // 处理 path
  proxyReqPathResolver: (req) => {
    // api/v2/banners
    console.log(req.url, "proxy")
    return '/api/v2/banners'
  }
}))

// 注意在 ssr 中渲染的时候， 不能存在root节点下有 TEXT 节点， 如: 空格
const templateFn = (content, store, styleStr) => {
  return `
  <!DOCTYPE html>
  <html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>${styleStr}</style>
  </head>
  <body>
    <div id="root">${content}</div>
    <script>
      // 服务器注水
      window.context = {
        state: ${JSON.stringify(store.getState())}
      }
    </script>
    <script src="/index.js"></script>
  </body>
  </html>
  `
}


app.use("/", async (req, res) => {

  // 这里需要将 store 传递给组件
  const store = getStore()
  // 如果这里将 data 填充到 store 中, 根据 用户的请求 path 来获取异步数据
  // routes.some((route) => {
  //   const match = matchPath(req.path, route)
  //   if (match) {
  //     matchRoutes.push(route)
  //     // matchRoutes(route)
  //   }
  // })

  // node server 要做中间服务器来做 api 服务器的代理服务器

  const context = {
    name: "liyao",
    css: []
  };
  const promises = [];
  const matchedRoutes = matchRoutes(routes, req.path)
  matchedRoutes.forEach((item) => {
    if (item.route.loadData) {
      promises.push(item.route.loadData(store))
    }
  })
  // console.log(matchedRoutes);
  await Promise.all(promises)

  // console.log(store.state)
  // StaticRouter: 不知道当前的 path，需要传递, context 中的
  const content = renderToString(
    <Provider store={store}>
      <StaticRouter
        context={context} location={req.path}>
        <Header staticContext={context} />
        <Switch>
          {/* {renderRoutes(routes)} */}
          {routes.map((route) => {
            return <Route {...route} key={`Route_${route.path}`} />
          })}
        </Switch>
      </StaticRouter>
    </Provider>
  )

  // 经过上面的路由处理之后， 如果在组件中有使用 <Redirect to="/" /> 301 的重定向， react-router-config 会向 context 中注入
  // 重定向的数据
  // 这里获取到 css 样式之后， 可以向 context 中注入样式
  // 多组件的样式如何组合？ =>
  console.log(context);

  const styleStr = context.css.length > 0 ? context.css.join("\n") : ""

  res.send(templateFn(content, store, styleStr))
  // const ret = renderToNodeStream(<Home />);
  // res.send(ret.pipe())
  // ret.pipe(res);
  // res.pipe()
})

app.listen(9999);